package com.tianji.promotion.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.dto.course.CategoryBasicDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.promotion.domain.dto.CouponFormDTO;
import com.tianji.promotion.domain.dto.CouponIssueFormDTO;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.CouponScope;
import com.tianji.promotion.domain.query.CouponQuery;
import com.tianji.promotion.domain.vo.CouponDetailVO;
import com.tianji.promotion.domain.vo.CouponPageVO;
import com.tianji.promotion.domain.vo.CouponScopeVO;
import com.tianji.promotion.enums.CouponStatus;
import com.tianji.promotion.enums.ObtainType;
import com.tianji.promotion.mapper.CouponMapper;
import com.tianji.promotion.service.ICouponScopeService;
import com.tianji.promotion.service.ICouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.service.IExchangeCodeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 优惠券的规则信息 服务实现类
 * </p>
 *
 * @author 老李头儿
 * @since 2025-04-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {

    private final ICouponScopeService ScopeService;
    private final IExchangeCodeService codeService;
    private final CategoryCache categoryCache;


    /**
     * @param dto
     * @Description 新增优惠券接口
     * @Author 老李头儿
     * @Date 2025年04月03 15:32:29
     * @Return void
     **/

    @Override
    public void saveCoupon(CouponFormDTO dto) {
        //转换dto为po
        Coupon coupon = BeanUtil.toBean(dto, Coupon.class);
        //保存优惠券
        this.save(coupon);
        //保存优惠券使用范围
        if (!dto.getSpecific()) {
            return;
        }
        //保存优惠券使用范围
        Long couponId = coupon.getId();
        List<Long> scopes = dto.getScopes();
        if (scopes == null) {
            throw new BizIllegalException("优惠券使用范围不能为空");
        }
        //保存优惠券使用范围
        List<CouponScope> scopeList = scopes.stream()
                .map(b -> new CouponScope().setCouponId(couponId).setBizId(b)).collect(Collectors.toList());

        //批量保存
        this.ScopeService.saveBatch(scopeList);


    }

    /**
     * @param query
     * @Description 分页查询优惠券接口
     * @Author 老李头儿
     * @Date 2025年04月03 20:42:55
     * @Return com.tianji.common.domain.dto.PageDTO<com.tianji.promotion.domain.vo.CouponPageVO>
     **/

    @Override
    public PageDTO<CouponPageVO> queryCouponPage(CouponQuery query) {
        Integer status = query.getStatus();
        String name = query.getName();
        Integer type = query.getType();
        //分页查询
        Page<Coupon> page = this.lambdaQuery().eq(status != null, Coupon::getStatus, status)
                .eq(type != null, Coupon::getType, type)
                .like(name != null, Coupon::getName, name)
                .page(query.toMpPage());
        //处理返回结果
        List<Coupon> records = page.getRecords();
        if (page == null) {
            return PageDTO.empty(page);
        }
        List<CouponPageVO> list = BeanUtil.copyToList(records, CouponPageVO.class);
        return PageDTO.of(page, list);
    }


    /**
     * @param dto
     * @Description 发放优惠券接口
     * @Author 老李头儿
     * @Date 2025年04月03 20:58:53
     * @Return void
     **/

    @Override
    @Transactional
    public void issueCoupon(CouponIssueFormDTO dto) {
        //查询优惠券
        Coupon coupon = this.getById(dto.getId());
        //判断优惠券是否存在
        if (coupon == null) {
            throw new BizIllegalException("优惠券不存在");
        }
        //判断优惠券状态是否可以发放
        if (coupon.getStatus() != CouponStatus.DRAFT && coupon.getStatus() != CouponStatus.PAUSE) {
            throw new BizIllegalException("优惠券状态错误!!!");
        }
        //更新优惠券状态为发放中(先判断优惠券是否在发放时间内)
        Coupon c = BeanUtils.copyBean(dto, coupon.getClass());
        LocalDateTime issueBeginTime = dto.getIssueBeginTime();
        if (!issueBeginTime.isAfter(LocalDateTime.now()) || issueBeginTime == null) {
            c.setIssueBeginTime(LocalDateTime.now());
            c.setStatus(CouponStatus.ISSUING);
        } else {
            c.setStatus(CouponStatus.UN_ISSUE);
        }

        this.updateById(c);

        //异步发放优惠券(状态为代发放且必须是兑换券兑换)
        if (coupon.getObtainWay() == ObtainType.ISSUE && coupon.getStatus() == CouponStatus.DRAFT) {
            coupon.setIssueEndTime(c.getIssueEndTime());
            codeService.asyncGenerateCode(coupon);
        }


    }

    /**
     * @param dto
     * @Description 修改优惠券接口
     * @Author 老李头儿
     * @Date 2025年04月04 13:24:09
     * @Return void
     **/

    @Override
    public void updateCoupon(CouponIssueFormDTO dto) {
        //查询优惠券id
        Long id = dto.getId();
        //查询优惠券
        Coupon coupon = this.lambdaQuery()
                .eq(Coupon::getId, id)
                .eq(Coupon::getStatus, CouponStatus.DRAFT)
                .one();
        if (coupon == null) {
            throw new BizIllegalException("优惠券不存在");
        }
        List<CouponScopeVO> scopes = this.queryCouponDetail(id).getScopes();
        if (scopes != null) {
            //删除优惠券使用范围
           this.deleteCoupon(dto);
            //保存优惠券使用范围
            List<CouponScope> scopeList = scopes.stream()
                    .map(b -> new CouponScope().setCouponId(id).setBizId(b.getId())).collect(Collectors.toList());
            //批量保存
            this.ScopeService.saveBatch(scopeList);
        }


    }

    /**
     * @param dto
     * @Description 删除优惠券接口
     * @Author 老李头儿
     * @Date 2025年04月04 13:59:05
     * @Return void
     **/

    @Override
    public void deleteCoupon(CouponIssueFormDTO dto) {
        //查询优惠券
        Coupon coupon = this.getById(dto.getId());
        if (coupon == null) {
            throw new BizIllegalException("优惠券不存在");
        }
        if (coupon.getStatus() == CouponStatus.DRAFT) {
            //删除优惠券
            this.removeById(dto.getId());
        }

    }

    /**
     * @param id
     * @Description 根据id查询优惠券详情接口
     * @Author 老李头儿
     * @Date 2025年04月04 14:17:37
     * @Return com.tianji.promotion.domain.vo.CouponDetailVO
     **/

    @Override
    public CouponDetailVO queryCouponDetail(Long id) {
        //查询优惠券
        Coupon coupon = this.getById(id);
        //拷贝属性到vo
        if (coupon == null) {
            throw new BizIllegalException("优惠券不存在");
        }
        CouponDetailVO vo = BeanUtils.copyBean(coupon, CouponDetailVO.class);
        //查询优惠券使用范围
        if (vo == null) {
            throw new BizIllegalException("优惠券不存在");
        }
        List<CouponScope> scopes = ScopeService.lambdaQuery()
                .eq(CouponScope::getCouponId, id)
                .list();
        if (CollUtils.isNotEmpty(scopes)) {
            scopes.stream().forEach(s -> {s.setId(s.getBizId());
            });
            List<CouponScopeVO> scopeVOS = BeanUtil.copyToList(scopes, CouponScopeVO.class);
            vo.setScopes(scopeVOS);
            //设置优惠券对应业务名称
            List<String> categoryNameList = categoryCache.getCategoryNameList
                    (scopes.stream().map(CouponScope::getBizId).collect(Collectors.toList()));
            if (CollUtils.isNotEmpty(categoryNameList)) {
                //循环给scopeVOS里的name赋值
                for (int i = 0; i < scopeVOS.size(); i++) {
                    scopeVOS.get(i).setName(categoryNameList.get(i));
                }
                vo.setScopes(scopeVOS);
            }

        }

        return vo;
    }


    /**
     * @param id
     * @Description 暂停发放优惠券接口
     * @Author 老李头儿
     * @Date 2025年04月04 15:11:31
     * @Return void
     **/
    @Override
    public void pauseCoupon(Long id) {
        //查询优惠券
        Coupon coupon = this.getById(id);
        if (coupon == null) {
            throw new BizIllegalException("优惠券不存在");
        }
        if (coupon.getStatus() == CouponStatus.ISSUING) {
            //暂停发放优惠券
            coupon.setStatus(CouponStatus.PAUSE);
            this.updateById(coupon);
        }

    }
}
